/*
 * 
 */
package es.drOsu.game;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import javax.xml.datatype.Duration;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.DialogInterface.OnDismissListener;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.Paint.Style;
import android.graphics.drawable.Drawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

import com.echonest.api.v4.EchoNestAPI;
import com.echonest.api.v4.EchoNestException;
import com.echonest.api.v4.Song;
import com.echonest.api.v4.SongParams;
import es.drOsu.common.Circle;
import es.drOsu.common.Constants;
import es.drOsu.common.Drag;
import es.drOsu.common.HitScore;
import es.drOsu.common.LifeBar;
import es.drOsu.common.Music;
import es.drOsu.common.Tools;

// TODO: Auto-generated Javadoc
/**
 * The Class GameNewView vista donde se dibujara y tratara todo el juego.
 *
 * @author darkbeast
 */
public class GameNewView extends GameNew implements SensorEventListener, OnClickListener{
	
	/** The num path. */
	private int numPath=0;
	
	/** The Constant TAG variable para la depuracion en el LogCat. */
	private static final String TAG = "GameNewView";
	
	/** The Constant CIRCLE sirve para saber si cuando tengamos un recorrido es un circulo. */
	private static final String CIRCLE = Circle.class.getName();
	
	/** The Constant DRAG sirve para saber si cuando tengamos un recorrido es un drag. */
	private static final String DRAG = Drag.class.getName();
	
	/** The m contex contexto de la actividad. */
	private Context mContex;
	
	/** The score puntuacion que lleva el jugador en el juego. */
	private int score;
	
	/** The x motion event corrdenada x cuando el jugador hace click en pantalla. */
	private float xMotionEvent =0;
	
	/** The y motion event corrdenada y cuando el jugador hace click en pantalla. */
	private float yMotionEvent =0;
	
	/** The first drag motion event variable de control para ver si es al primer movimiento del drag. */
	private boolean firstDragMotionEvent = true;
	
	// Flags for game state and options.
	/** The loaded para ver si el juego ha cargado todos los elementos correctamente. */
	boolean loaded = false;
	
	/** The paused para ver si el juego esta pausado. */
	boolean paused;
	
	/** The error bmp para ver si se ha conseguido o no obtener los bpm. */
	boolean errorbpm=false;
	
	/** The error bmp para ver si se han calculado los bpm. */
	boolean bpmCalculated=false;
	
	/** The playing para ver si el juego se esta jugando. */
	boolean playing = false;
	
	//Drawables
	/** The path. */
	private ArrayList<Object> path = null;
	
	/** The path de todo el juego en modo normal. */
	private ArrayList<Object> pathReadedFile = null;
	
	/** The hit50. */
	private HitScore hit50=null;
	
	/** The hit100. */
	private HitScore hit100=null;
	
	/** The hit300. */
	private HitScore hit300=null;
	
	/** The fail. */
	private HitScore fail=null;
	
	/** The hit100bonus. */
	private HitScore hit100bonus=null;
	
	/** The hit300bonus. */
	private HitScore hit300bonus=null;
	
	/** The hit300extra bonus. */
	private HitScore hit300extraBonus=null;
	
	/** The mp guarda la informacion del reproductor de la cancion elegida por el jugador. */
	private MediaPlayer mp = null;
	
	/** The mpdrag sonido para el drag. */
	private MediaPlayer mpdrag = null;
	
	/** The mpfail sonido para cuando falla un movimiento. */
	private MediaPlayer mpfail = null;
	
	/** The mpcountdown sonido para la cuenta atras. */
	private MediaPlayer mpcountdown = null;
	
	/** The life bar. */
	private LifeBar lifeBar=null;
	
	/** The circle01 guarda la imagen para el circulo 1. */
	private Drawable circle01 = null;
	
	/** The circle02 guarda la imagen para el circulo 2. */
	private Drawable circle02 = null;
	
	/** The circle03 guarda la imagen para el circulo 3. */
	private Drawable circle03 = null;
	
	/** The circle04 guarda la imagen para el circulo 4. */
	private Drawable circle04 = null;
	
	/** The circle05 guarda la imagen para el circulo 5. */
	private Drawable circle05 = null;
	
	/** The circle06 guarda la imagen para el circulo 6. */
	private Drawable circle06 = null;
	
	/** The circle07 guarda la imagen para el circulo 7. */
	private Drawable circle07 = null;
	
	/** The circle08 guarda la imagen para el circulo 8. */
	private Drawable circle08 = null;
	
	/** The circle09 guarda la imagen para el circulo 9. */
	private Drawable circle09 = null;
	
	/** The circle10 guarda la imagen para el circulo 10. */
	private Drawable circle10 = null;
	
	/** The sliderfollowcircle guarda el bitmap del circulo de seguimiento de la bola del drag. */
	private Bitmap sliderfollowcircle = null;
	
	/** The ball start guarda el bitmap del primer movimiento de la bola del drag. */
	private Bitmap ballStart = null;
	
	/** The approachcircle guarda el bitmap del circulo de aproximacion. */
	private Bitmap approachcircle = null;
	
	/** The approachcircle drawable listado con todos los circulos de aproximacion dependiendo del tick en el que se encuentre. */
	private ArrayList<Drawable> approachcircleDrawable = null;
	
	/** The sliderfollowcircle drawables listado con todos los circulos de aproximacion dependiendo del tick en el que se encuentre. */
	private ArrayList<Drawable> sliderfollowcircleDrawables = null;
	
	/** The ball listado con todos las imagenes de la bola del drag. */
	private Drawable [] ball = new Drawable[10];
	
	//Colors
	
	/** The red color rojo para el pintado de diferentes elementos. */
	private Paint red = new Paint();
	
	/** The red color violeta para el pintado de los slider de baja calidad. */
	private Paint violetSlider = new Paint();
	
	/** The violetCircle color violeta para el pintado de los circulos de baja calidad. */
	private Paint violetCircle = new Paint();
	
	/** The redbar color rojo para la barra de vida. */
	private Paint redbar = new Paint();
	
	/** The black color negro para el pintado de diferentes elementos. */
	private Paint black = new Paint();
	
	/** The blackorientation color negro para la linea negra de la brujula. */
	private Paint blackorientation = new Paint();
	
	/** The degrees paint color elegido para la linea que ha de seguir la negra en la brujula. */
	private Paint degreesPaint = new Paint();
	
	/** The white color blanco para el pintado de diferentes elementos. */
	private Paint white = new Paint();
	
	/** The white color blanco para el texto de los circulos sin efectos graficos. */
	private Paint whiteText = new Paint();
	
	/** The green color verde para el pintado de diferentes elementos. */
	private Paint green = new Paint();
	
	/** The green color verde para el pintado del circulo de seguimiento de la bola del drag. */
	private Paint greenSlider = new Paint();
	
	/** The blue_countdown color azul para el pintado de los numeros y letras de la cuenta atras. */
	private Paint blue_countdown = new Paint();
	
	/** The dark_pink_bar rosa oscuro para el pintado del relleno del shakebar. */
	private Paint dark_pink_bar = new Paint();
	
	/** The number numero en el que estamos actualmente en el juego. */
	private int number = 0;
	
	/** The number numero en el que estamos actualmente en el juego en el modo normal. */
	private int numberNormal = 0;
	
	/** The path iteration. */
	private int pathIteration = 0;
	
	/** The firsttime estado para ver si estamos ya emepezando el juego. */
	private boolean firsttime = true;
	
	/** The firsttimedraw variable de controla para el primer pintado. */
	private boolean firsttimedraw = true;
	
	/** The countdown estado para ver si estamos en la cuenta atras. */
	private boolean countdown = true;
	
	/** The shakebar estado para ver si estamos en el bonus de shakebar. */
	private boolean shakebar = false;
	
	/** The orientation estado para ver si estamos en el bonus de la brujula. */
	private boolean orientation = false;
	
	/** The game estado para ver si estamos en el juego en si. */
	private boolean game = false;
	
	/** The freememory estado para liberar la memoria o ver si se ha liberado. */
	private boolean freememory = false;
	
	/** The soundsEffects estado para saber si se usan o no los efectos sonoros. */
	private boolean soundsEffects = false;
	
	/** The graphicsEffects estado para saber si se usan o no los efectos graphicos. */
	private boolean graphicsEffects = true;
	
	/** The number count down contador para ver en que momentos de la cuenta atras estamos. */
	private int numberCountDown = 0;
	
	/** The bpm tempo de la cancion elegida por el jugador. */
	private double bpm=0;
	
	/** The time timer tiempo de refresco que tiene la vista dependiendo del tempo. */
	private long timeTimer=0;
	
	/** The game mode modo de juego que ha elegido el jugador. */
	private int gameMode = -1;
	
	/** The game difficulty dificultad de juego que ha elegido el jugador. */
	private int gameDifficulty = -1;
	
	/** The user usuario o jugador que esta jugando al juego. */
	private String user = null;
	
	/** The music path ruta de acceso a la sd de la cancion elegida por el usuario. */
	private String musicPath = null;
	
	/** The height alto de la pantalla del dispositivo. */
	private int height;
	
	/** The width ancho de la pantalla del dispositivo. */
	private int width;
	
	//Scores
	/** The combo100 variable de control para ver si consigue un bonus de 100. */
	private int combo100 = 0;
	
	/** The combo300 variable de control para ver si consigue un bonus de 300. */
	private int combo300 = 0;
	
	/** The count fail numero de veces que consigue un fallo en algun movimiento. */
	private int countFail = 0;
	
	/** The count50 numero de veces que consigue un 50 de puntuacion. */
	private int count50 = 0;
	
	/** The count100 numero de veces que consigue un 100 de puntuacion. */
	private int count100 = 0;
	
	/** The count100 bonus numero de veces que se consigue un bonus de 100. */
	private int count100Bonus = 0;
	
	/** The count300 numero de veces que consigue un 300 de puntuacion. */
	private int count300 = 0;
	
	/** The count300 bonus numero de veces que se consigue un bonus de 300. */
	private int count300Bonus = 0;
	
	/** The count300 beat numero de veces que se consigue un bonus extra de 300. */
	private int count300Beat = 0;
	
	/** The max length combo variable de control para llevar el combo mas largo realizado por el jugador. */
	private int maxLengthCombo = 0;
	
	/** The max length combo final el numero maximo del combo conseguido por el jugador. */
	private int maxLengthComboFinal = 0;
	
	//Shackebar bonus
	/** The m accelerometer values valores x,y,z del acelerometro. */
	private float[] mAccelerometerValues={0,0,0};
	
	/** The m sensor manager guarda el manejador de los sensores de los diferentes acelerometros del dispositivo. */
	private SensorManager mSensorManager;
	
	/** The sensor list lista con todos los sensores de los que dispone el dispositivo. */
	private List<Sensor> sensorList;
	
	/** The start x coordenada x para el empiece del dibujado de la shakebar. */
	private int startX = 0;
	
	/** The start y coordenada y para el empiece del dibujado de la shakebar. */
	private int startY = 0;
	
	/** The stop x coordenada x para el finalizado del dibujado de la shakebar. */
	private int stopX = 0;
	
	/** The stop y coordenada y para el finalizado del dibujado de la shakebar. */
	private int stopY = 0;
	
	/** The background_bar imagen con la plantilla de la barra de shakebar. */
	private Drawable background_bar = null;
	
	/** The pink_bar imagen con el fondo de la barra de shakebar. */
	private Drawable pink_bar = null;
	
	//orientation bonus
	/** The sel x corrdenada x donde empieza el pintado de la brujula. */
	private float selX = 0;
	
	/** The sel y corrdenada y donde empieza el pintado de la brujula. */
	private float selY = 0;
	
	/** The stop ox coordenada x donde finliza el pintado de las lineas de la brujula. */
	private float stopOX = 0;
	
	/** The stop oy coordenada y donde finliza el pintado de las lineas de la brujula. */
	private float  stopOY = 0;
	
	/** The degrees grados de giro de la linea roja respecto de su centro. */
	private float degrees = (float) Math.random()*360;
	
	/** The m orientation values guarda los valores de los grados para dibujar la imagen de la brujula. */
	private float[] mOrientationValues = {200,200,200};
	
	/** The m magnetic values guarda los valores devueltos por el acelerometro de magnetismo. */
	private float[] mMagneticValues;
	//private float[] mAccelerometerValues;
	/** The compass guarda la imagen de la brujula. */
	private Drawable compass = null;
	
	/** The dialog guarda el cuado de dialogo del menu pausa del juego. */
	private Dialog dialog;
	
	/**
	 * Instantiates a new game new view crea una nueva vista de juego y asigna el tiempo de refresco de la misma pero sin atributos.
	 *
	 * @param context the context contexto de la actividad
	 */
	public GameNewView(Context context) {
		super(context);
		mContex=context;
		setUpdateTimer(500);
	}
	
	/**
	 * Instantiates a new game new view crea una nueva vista de juego y asigna el tiempo de refresco de la misma pero con atributos.
	 *
	 * @param context the context
	 * @param attrs the attrs
	 */
	public GameNewView(Context context, AttributeSet attrs){
		super(context,attrs);
		mContex=context;
		setUpdateTimer(500);
		
	}
	
	/* (non-Javadoc)
	 * @see es.drOsu.game.GameNew#initialize()
	 */
	@Override
	protected void initialize(){
		int width = getWidth();
		int height = getHeight();
		this.height=height;
		this.width=width;
		Bundle bundle = ((Activity) mContex).getIntent().getExtras();
		gameMode = bundle.getInt(Constants.keyGameMode);
		user = bundle.getString(Constants.keyUser);
		musicPath = bundle.getString(Constants.keyPath);
		gameDifficulty = bundle.getInt(Constants.keyGameDifficulty);
		
		SharedPreferences prefs = mContex.getSharedPreferences(user,Context.MODE_PRIVATE);
		if(prefs.getString(Constants.sharedPreferencesSoundsEffects, Constants.sharedPreferencesSoundEffectsUncheck).contains(Constants.sharedPreferencesSoundEffectsUncheck)){
			soundsEffects=false;
		}else soundsEffects=true;
		if(prefs.getString(Constants.sharedPreferencesGraphicsEffects, Constants.sharedPreferencesGraphicsEffectsUncheck).contains(Constants.sharedPreferencesGraphicsEffectsUncheck)){
			graphicsEffects=false;
		}else graphicsEffects=true;
		
		//Log.d(TAG,"gameMode: "+gameMode+" user: "+user);
		
		//shakebar bonus initialize
		initializeShakeBar(width, height);
		//orientation bonus initialize
		initializeOrientation(width,height);
		
		
		mpfail = MediaPlayer.create(mContex, R.raw.fail);
		hit50=new HitScore(width,height, getImage(R.drawable.hit50),mContex);
		hit100=new HitScore(width,height, getImage(R.drawable.hit100),mContex);
		hit300=new HitScore(width,height, getImage(R.drawable.hit300),mContex);
		fail=new HitScore(width,height, getImage(R.drawable.hit0),mContex);
		hit100bonus=new HitScore(width, height, getImage(R.drawable.hit100k), mContex);
		hit300bonus=new HitScore(width, height, getImage(R.drawable.hit300k), mContex);
		hit300extraBonus=new HitScore(width, height, getImage(R.drawable.hit300g), mContex);
		//sonidos
		mp = MediaPlayer.create(mContex, R.raw.whistleogg);
		mpdrag = MediaPlayer.create(mContex, R.raw.drag);
		mpcountdown = MediaPlayer.create(mContex, R.raw.countdown);
		
		lifeBar=new LifeBar(width, height, getImage(R.drawable.scorebar_bg), mContex);
		lifeBar.updateBar();
		
		white.setColor(getResources().getColor(R.color.white));
		red.setColor(getResources().getColor(R.color.red));
		
		redbar.setColor(getResources().getColor(R.color.red));
		green.setColor(getResources().getColor(R.color.green));
		black.setColor(getResources().getColor(R.color.black));
		blackorientation.setColor(getResources().getColor(R.color.black));
		blue_countdown.setColor(getResources().getColor(R.color.blue_countdown));
		dark_pink_bar.setColor(getResources().getColor(R.color.drak_pink_bar));
		
		redbar.setStyle(Style.STROKE);
		redbar.setStrokeWidth(getHeight()/12);
		if(!graphicsEffects){
			violetSlider.setColor(getResources().getColor(R.color.violet_slider));
			violetSlider.setStyle(Style.STROKE);
			violetSlider.setStrokeWidth(getHeight()/36);
			greenSlider.setColor(getResources().getColor(R.color.green_slider));
			greenSlider.setStyle(Style.STROKE);
			greenSlider.setStrokeWidth(getHeight()/36);
			whiteText.setColor(getResources().getColor(R.color.white));
			whiteText.setTextSize(getHeight()/12);
			whiteText.setTextAlign(Paint.Align.CENTER);
			violetCircle.setColor(getResources().getColor(R.color.violet_slider));
		}
		
		
		black.setTextSize(getHeight()/12);
		black.setStyle(Style.FILL);
		black.setTextAlign(Paint.Align.RIGHT);
		
		blackorientation.setColor(getResources().getColor(R.color.black));
		blackorientation.setStyle(Style.STROKE);
		blackorientation.setStrokeWidth(8);
		
		degreesPaint.setColor(getResources().getColor(R.color.red));
		degreesPaint.setStyle(Style.STROKE);
		degreesPaint.setStrokeWidth(8);
		
		Typeface face=Typeface.createFromAsset(mContex.getAssets(), "fonts/BILLD.TTF");
		blue_countdown.setTypeface(face);
		blue_countdown.setStyle(Style.STROKE);
		System.gc();
		//Log.d(TAG, "colores");
		loadBitmaps(width,height);
		//Log.d(TAG, "bitmaps");
		
		if(gameMode==Constants.HARDCORE){
			Log.d(TAG, "hardcore mode");
			generatePath(width,height);
		}else{
			if(gameMode==Constants.NORMAL){
				Log.d(TAG,"normal mode");
				String pathGame = "";
				switch (gameDifficulty) {
				case Constants.EASY:
					pathGame=musicPath.substring(0, musicPath.length()-4);
					pathGame=pathGame+Constants.normalEasy;
					break;
				case Constants.MEDIUM:
					pathGame=musicPath.substring(0, musicPath.length()-4);
					pathGame=pathGame+Constants.normalMedium;
					break;
				case Constants.CHAMPION:
					pathGame=musicPath.substring(0, musicPath.length()-4);
					pathGame=pathGame+Constants.normalChampion;					
					break;
				
				}
				Log.d(TAG, "path guardado: "+pathGame);
				File file = new File(pathGame);
				if(file.exists()){
					Log.d(TAG, "existe");
					readFilePath(file);
				}else{
					Log.d(TAG, "no existe");
					createFilePath(file);
				}
			}
		}
		//Log.d(TAG, "path");
		initGame();
		//Log.d(TAG, "bien iniciado");
	}
	
	/**
	 * Read file path.
	 * 
	 * @param file
	 *            the file
	 */
	private void readFilePath(File file) {
		BufferedReader reader;
		pathReadedFile=new ArrayList<Object>();
		try {
			reader = new BufferedReader(new FileReader(file));
		
		String linea = reader.readLine();
		int num = 1;
		while (linea != null)
		{
		   if(linea.charAt(0)=='C'){
			   int x = Integer.parseInt(linea.substring(2, 5));
			   int y = Integer.parseInt(linea.substring(6, 9));
				   pathReadedFile.add(createCircleNormalMode(height, mContex, x, y, 0, num));
		   }
		   if(linea.charAt(0)=='c'){
			   int x = Integer.parseInt(linea.substring(2, 5));
			   int y = Integer.parseInt(linea.substring(6, 9));
			   
			   pathReadedFile.add(createCircleNormalMode(height, mContex, x, y, 2, num));
		   }
		   if(linea.charAt(0)=='D'){
			   int xStart = Integer.parseInt(linea.substring(2, 5));
			   int xEnd = Integer.parseInt(linea.substring(6, 9));
			   int yStart = Integer.parseInt(linea.substring(10, 13));
			   int yEnd = Integer.parseInt(linea.substring(14, 17));
			   pathReadedFile.add(createDragNormalMode(height, mContex, xStart, xEnd, yStart, yEnd, num));
		   }
		   //lineaTotal.append(System.getProperty("line.separator"));
		   linea = reader.readLine();
		   
		   if(num>=10)
			   num=1;
		   else
			   num++;
		}
		//Log.d(TAG, "lineatotal\n"+lineaTotal);
		reader.close();
		path=new ArrayList<Object>();
		for(int i=numberNormal;i<numberNormal+10;i++){
			path.add(pathReadedFile.get(i));
		}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Creates the file path.
	 * 
	 * @param file
	 *            the file
	 */
	private void createFilePath(File file) {
		calculateBPM(musicPath);
		if(!errorbpm){
			bpmCalculated=true;
			Log.d(TAG, "bmp: "+bpm);
			double seg=60/bpm;
			//Log.d(TAG, "seg: "+seg);
			
			if(gameDifficulty==Constants.CHAMPION){
				timeTimer = (long)((1000*seg/2));
			}
			if(gameDifficulty==Constants.MEDIUM){
				timeTimer = (long)((1000*seg/1.5));
			}
			if(gameDifficulty==Constants.EASY){
				timeTimer = (long)((1000*seg));
			}			
		}else{
			halt();
			Intent intentMain = new Intent(mContex, DrosuMain.class);
			paused=true;
			firsttime=true;
			resume();
			mContex.startActivity(intentMain);
		}
		try {
			int circle = (int) (timeTimer*40);
			int dcircle = circle/2;
			int total = (circle+dcircle)/2;
			int numberOfPath = Music.duration(musicPath)/total;
			Log.d(TAG, "nuemero de path: "+numberOfPath);
			//file.createNewFile();
			PrintWriter pw = new PrintWriter(file);
			pathReadedFile=new ArrayList<Object>();
			for(int j=0;j<numberOfPath;j++){
				generatePath(width, height);
				for(int i=0;i<path.size();i++){
					pathReadedFile.add(path.get(i));
					if(path.get(i).getClass().getName().compareTo(CIRCLE)==0){
						Circle c = (Circle) path.get(i);						
						if(c.tick==0){
							pw.write("C "+c.coorX+" "+c.coorY+System.getProperty("line.separator"));
						}else{
							pw.write("c "+c.coorX+" "+c.coorY+System.getProperty("line.separator"));
						}
					}else{
						if(path.get(i).getClass().getName().compareTo(DRAG)==0){
							Drag d = (Drag) path.get(i);
							pw.write("D "+d.coorXstart+" "+d.coorXend+" "+d.coorYstart+" "+d.coorYend+System.getProperty("line.separator"));
						}
					}
				}
			}
			pw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	/**
	 * Initialize orientation incializa todas las variables necesarias para el pintado de la fase de bonus de la brujula.
	 *
	 * @param width the width ancho de la pantalla del dispositivo
	 * @param height the height alto de la pantalla del dispositivo
	 */
	private void initializeOrientation(int width, int height) {
		compass = Tools.resizeImage(mContex, R.drawable.compass, height, height,true,270);
		selX = width/2;
		stopOX = selX;
		selY = height/2;
		stopOY = selY;
	}

	/**
	 * Initialize shake bar inicializa todas las variables necesarias para el pintado de la fase de bonus del shakebar.
	 *
	 * @param width the width ancho de la pantalla del dispositivo
	 * @param height the height alto de la pantalla del dispositivo
	 */
	private void initializeShakeBar(int width,int height){
		mSensorManager = Tools.getSensor();
		startX = (int) (width/2 - (25*mContex.getResources().getDisplayMetrics().density));
		stopX = (int) (startX+50*mContex.getResources().getDisplayMetrics().density);
		startY = height*3/4;
		stopY = height*1/4;
		background_bar = Tools.resizeImage(BitmapFactory.decodeResource(mContex.getResources(),R.drawable.background_bar), stopX-startX,startY-stopY);
		pink_bar = Tools.resizeImage(BitmapFactory.decodeResource(mContex.getResources(),R.drawable.pink_bar), stopX-startX,startY-stopY);
		stopY=(int) (startY-mContex.getResources().getDisplayMetrics().density);
	}
	
	/**
	 * Load bitmaps cargado de todos los Bitmaps Drawables o imagenes que van ser usadas durante el dibujado del juego.
	 *
	 * @param width the width ancho de la pantala del dispositivo
	 * @param height the height alto de la pantalla del dispositivo
	 */
	private void loadBitmaps(int width,int height) {
		int radius= (int) (height*mContex.getResources().getDisplayMetrics().density/12*2);
		if(graphicsEffects){
			circle01 = Tools.resizeImage(getImage(R.drawable.na01),radius,radius);
			circle02 = Tools.resizeImage(getImage(R.drawable.na02),radius,radius);
			circle03 = Tools.resizeImage(getImage(R.drawable.na03),radius,radius);
			circle04 = Tools.resizeImage(getImage(R.drawable.na04),radius,radius);
			circle05 = Tools.resizeImage(getImage(R.drawable.na05),radius,radius);
			circle06 = Tools.resizeImage(getImage(R.drawable.na06),radius,radius);
			circle07 = Tools.resizeImage(getImage(R.drawable.na07),radius,radius);
			circle08 = Tools.resizeImage(getImage(R.drawable.na08),radius,radius);
			circle09 = Tools.resizeImage(getImage(R.drawable.na09),radius,radius);
			circle10 = Tools.resizeImage(getImage(R.drawable.na10),radius,radius);
		
			sliderfollowcircle = getImage(R.drawable.sliderfollowcircle);
			approachcircle = getImage(R.drawable.approachcircle);
			int size=(int) (height*mContex.getResources().getDisplayMetrics().density/12*5);
			
			int newSize = 0;//size-((size-radius)/(maxTick-tick+1));
			approachcircleDrawable=new ArrayList<Drawable>();
			sliderfollowcircleDrawables=new ArrayList<Drawable>();
			for(int i=0;i<=Constants.maxTicks;i++){
				if(i==Constants.maxTicks){
					newSize=radius;
				}else
					newSize=size-(((size-radius)/(Constants.maxTicks))*i);//size-((size-radius)/(Constants.maxTicks-i+1));
				approachcircleDrawable.add(Tools.resizeImage(approachcircle, newSize, newSize));
				sliderfollowcircleDrawables.add(Tools.resizeImage(sliderfollowcircle, newSize, newSize));
			}
		}
		ballStart = getImage(R.drawable.sliderb0);
		
		ball[0]=Tools.resizeImage(getImage(R.drawable.sliderb0), radius, radius);
		ball[1]=Tools.resizeImage(getImage(R.drawable.sliderb1), radius, radius);
		ball[2]=Tools.resizeImage(getImage(R.drawable.sliderb2), radius, radius);
		ball[3]=Tools.resizeImage(getImage(R.drawable.sliderb3), radius, radius);
		ball[4]=Tools.resizeImage(getImage(R.drawable.sliderb4), radius, radius);
		ball[5]=Tools.resizeImage(getImage(R.drawable.sliderb5), radius, radius);
		ball[6]=Tools.resizeImage(getImage(R.drawable.sliderb6), radius, radius);
		ball[7]=Tools.resizeImage(getImage(R.drawable.sliderb7), radius, radius);
		ball[8]=Tools.resizeImage(getImage(R.drawable.sliderb8), radius, radius);
		ball[9]=Tools.resizeImage(getImage(R.drawable.sliderb9), radius, radius);

	}

	/**
	 * Generate path genera un recorrido con todos los movimientos de una ronda(10 movimientos por ronda).
	 *
	 * @param width the width ancho de la pantalla del dispositivo
	 * @param height the height alto de la pantalla del dispositivo
	 */
	private void generatePath(int width, int height) {
		numPath++;
		//Log.d(TAG, "numpath:"+numPath);
		path=new ArrayList<Object>();
		for(int i=0;i<10;i++){
			if(i==0){
				path.add(createCircle(width,height,mContex,i+1));
				Circle c = (Circle) path.get(i);
				if(!firsttime)
					c.tick=3;
				path.set(i, c);
			}else{
				int randomNumber = (int)(Math.random()*100);
				
				if(randomNumber>60 && randomNumber<=75)
					path.add(createDrag(width,height,mContex,i+1));
					
					//path.add(createCircle(width,height,mContex));
					if(randomNumber>=0 && randomNumber<=60)
						path.add(createCircle(width, height, mContex,i+1));
				if(randomNumber>75 && randomNumber<=100){	
					Circle c = createCircle(width,height,mContex,i+1);
					path.add(c);
					if(i<9){						
						path.add(createDobleCircle(c,i+2));
						i++;
					}
				}
			}
		}
	}

	/**
	 * Creates the drag crea un movimiento de drag.
	 *
	 * @param width the width ancho de la pantalla del dispositivo
	 * @param height the height alto de la pantalla del dispositivo
	 * @param context the context contexto de la actividad
	 * @param number the number numero en el que se encuentra dentro del recorrido
	 * @return the drag devuelve un movimiento de drag listo para ser usado
	 */
	private Drag createDrag(int width, int height,Context context,int number) {
		if(graphicsEffects){
			switch (number) {
			case 1:
				return new Drag(width, height,ballStart,circle01,sliderfollowcircleDrawables.get(1), context);
			case 2:
				return new Drag(width, height,ballStart,circle02,sliderfollowcircleDrawables.get(1), context);
			case 3:
				return new Drag(width, height,ballStart,circle03,sliderfollowcircleDrawables.get(1), context);
			case 4:
				return new Drag(width, height,ballStart,circle04,sliderfollowcircleDrawables.get(1), context);
			case 5:
				return new Drag(width, height,ballStart,circle05,sliderfollowcircleDrawables.get(1), context);
			case 6:
				return new Drag(width, height,ballStart,circle06,sliderfollowcircleDrawables.get(1), context);
			case 7:
				return new Drag(width, height,ballStart,circle07,sliderfollowcircleDrawables.get(1), context);
			case 8:
				return new Drag(width, height,ballStart,circle08,sliderfollowcircleDrawables.get(1), context);
			case 9:
				return new Drag(width, height,ballStart,circle09,sliderfollowcircleDrawables.get(1), context);
			case 10:
				return new Drag(width, height,ballStart,circle10,sliderfollowcircleDrawables.get(1), context);
			}
		}else{
			return new Drag(width, height, context);
		}
		return null;
		
	}
	
	/**
	 * Creates the drag crea un movimiento de drag a partir de los datos
	 * cargados del fichero.
	 * 
	 * @param height
	 *            the height alto de la pantalla del dispositivo
	 * @param context
	 *            the context contexto de la actividad
	 * @param cxStart
	 *            the cx start
	 * @param cxEnd
	 *            the cx end
	 * @param cyStart
	 *            the cy start
	 * @param cyEnd
	 *            the cy end
	 * @param number
	 *            the number numero en el que se encuentra dentro del recorrido
	 * @return the drag devuelve un movimiento de drag listo para ser usado
	 */
	private Drag createDragNormalMode(int height,Context context,int cxStart,int cxEnd, int cyStart,int cyEnd,int number) {
		if(graphicsEffects){
			switch (number) {
			case 1:
				return new Drag(height, ballStart, circle01, sliderfollowcircleDrawables.get(1), context, cxStart, cxEnd, cyStart, cyEnd);
			case 2:
				return new Drag(height, ballStart, circle02, sliderfollowcircleDrawables.get(1), context, cxStart, cxEnd, cyStart, cyEnd);
			case 3:
				return new Drag(height, ballStart, circle03, sliderfollowcircleDrawables.get(1), context, cxStart, cxEnd, cyStart, cyEnd);
			case 4:
				return new Drag(height, ballStart, circle04, sliderfollowcircleDrawables.get(1), context, cxStart, cxEnd, cyStart, cyEnd);
			case 5:
				return new Drag(height, ballStart, circle05, sliderfollowcircleDrawables.get(1), context, cxStart, cxEnd, cyStart, cyEnd);
			case 6:
				return new Drag(height, ballStart, circle06, sliderfollowcircleDrawables.get(1), context, cxStart, cxEnd, cyStart, cyEnd);
			case 7:
				return new Drag(height, ballStart, circle07, sliderfollowcircleDrawables.get(1), context, cxStart, cxEnd, cyStart, cyEnd);
			case 8:
				return new Drag(height, ballStart, circle08, sliderfollowcircleDrawables.get(1), context, cxStart, cxEnd, cyStart, cyEnd);
			case 9:
				return new Drag(height, ballStart, circle09, sliderfollowcircleDrawables.get(1), context, cxStart, cxEnd, cyStart, cyEnd);
			case 10:
				return new Drag(height, ballStart, circle10, sliderfollowcircleDrawables.get(1), context, cxStart, cxEnd, cyStart, cyEnd);
			}
		}else{
			return new Drag(height, context, cxStart, cxEnd, cyStart, cyEnd);
		}
		return null;
		
	}

	/**
	 * Creates the circle crea un movimiento de circulo basico(un click).
	 *
	 * @param width the width ancho de la pantalla del dispositivo
	 * @param height the height alto de la pantalla del dispositivo
	 * @param contex the contex contexto de la activdad
	 * @param number the number numero que el corresponde en el recorrido
	 * @return the circle devuelve un circulo listo para ser usado
	 */
	private Circle createCircle(int width, int height,Context contex,int number) {
		//Log.d(TAG, "n "+number);
		if(graphicsEffects){
			if(number==1){
				return new Circle(width, height,circle01,contex,0,0);
			}
			if(path.get(number-2).getClass().getName().compareTo(DRAG)==0 && number>1){
				Drag d = (Drag) path.get(number-2);
				switch (number) {
				case 1:			
					return new Circle(width, height,circle01,contex,d.coorXstart,d.coorYstart);
				case 2:
					return new Circle(width, height,circle02,contex,d.coorXstart,d.coorYstart);
				case 3:
					return new Circle(width, height,circle03,contex,d.coorXstart,d.coorYstart);
				case 4:
					return new Circle(width, height,circle04,contex,d.coorXstart,d.coorYstart);
				case 5:
					return new Circle(width, height,circle05,contex,d.coorXstart,d.coorYstart);
				case 6:
					return new Circle(width, height,circle06,contex,d.coorXstart,d.coorYstart);
				case 7:
					return new Circle(width, height,circle07,contex,d.coorXstart,d.coorYstart);
				case 8:
					return new Circle(width, height,circle08,contex,d.coorXstart,d.coorYstart);
				case 9:
					return new Circle(width, height,circle09,contex,d.coorXstart,d.coorYstart);
				case 10:
					return new Circle(width, height,circle10,contex,d.coorXstart,d.coorYstart);
				}
				
			}else{
				if(path.get(number-2).getClass().getName().compareTo(CIRCLE)==0 && number>0){
					Circle c = (Circle) path.get(number-2);
					switch (number) {
					case 1:			
						return new Circle(width, height,circle01,contex,c.coorX,c.coorY);
					case 2:
						return new Circle(width, height,circle02,contex,c.coorX,c.coorY);
					case 3:
						return new Circle(width, height,circle03,contex,c.coorX,c.coorY);
					case 4:
						return new Circle(width, height,circle04,contex,c.coorX,c.coorY);
					case 5:
						return new Circle(width, height,circle05,contex,c.coorX,c.coorY);
					case 6:
						return new Circle(width, height,circle06,contex,c.coorX,c.coorY);
					case 7:
						return new Circle(width, height,circle07,contex,c.coorX,c.coorY);
					case 8:
						return new Circle(width, height,circle08,contex,c.coorX,c.coorY);
					case 9:
						return new Circle(width, height,circle09,contex,c.coorX,c.coorY);
					case 10:
						return new Circle(width, height,circle10,contex,c.coorX,c.coorY);
					}
				}
			}
		}else{
			if(number==1){
				return new Circle(width, height,contex,0,0);
			}
			if(path.get(number-2).getClass().getName().compareTo(DRAG)==0 && number>1){
				Drag d = (Drag) path.get(number-2);
				return new Circle(width, height,contex,d.coorXstart,d.coorYstart);				
			}else{
				if(path.get(number-2).getClass().getName().compareTo(CIRCLE)==0 && number>0){
					Circle c = (Circle) path.get(number-2);
					return new Circle(width, height,contex,c.coorX,c.coorY);					
				}
			}
		}		
		return null;		
	}
	
	/**
	 * Creates the circle crea un movimiento de circulo basico(un click) cargado
	 * desde archivo.
	 * 
	 * @param height
	 *            the height alto de la pantalla del dispositivo
	 * @param context
	 *            the context
	 * @param cx
	 *            the cx coordenada x del circulo
	 * @param cy
	 *            the cy corrdenada y del ciruclo
	 * @param ntick
	 *            the ntick numero de ticks del circulo
	 * @param number
	 *            the number numero que el corresponde en el recorrido
	 * @return the circle
	 */
	private Circle createCircleNormalMode(int height,Context context,int cx,int cy,int ntick,int number) {
		//Log.d(TAG, "n "+number);
		if(graphicsEffects){
			switch (number) {
				case 1:			
					return new Circle(height, circle01, context, cx, cy, ntick);
				case 2:
					return new Circle(height, circle02, context, cx, cy, ntick);
				case 3:
					return new Circle(height, circle03, context, cx, cy, ntick);
				case 4:
					return new Circle(height, circle04, context, cx, cy, ntick);
				case 5:
					return new Circle(height, circle05, context, cx, cy, ntick);
				case 6:
					return new Circle(height, circle06, context, cx, cy, ntick);
				case 7:
					return new Circle(height, circle07, context, cx, cy, ntick);
				case 8:
					return new Circle(height, circle08, context, cx, cy, ntick);
				case 9:
					return new Circle(height, circle09, context, cx, cy, ntick);
				case 10:
					return new Circle(height, circle10, context, cx, cy, ntick);
			}
				
		}else{		
			return new Circle(height, context, cx, cy, ntick);
				
		}		
		return null;		
	}
	
	/**
	 * Creates the doble circle genera un movimiento de doble circulo(doble click).
	 *
	 * @param circle the circle se pasa el circulo anterior para haceder a sus datos y poner el segundo al lado de este
	 * @param number the number numero en que le corresponde en el recorrido
	 * @return the circle devuelve un doble circulo lista para ser usado
	 */
	private Circle createDobleCircle(Circle circle,int number) {
		
		//return new Circle(circle);
		if(graphicsEffects){
			switch (number) {
			case 1:
				return new Circle(circle,circle01);
			case 2:
				return new Circle(circle,circle02);
			case 3:
				return new Circle(circle,circle03);
			case 4:
				return new Circle(circle,circle04);
			case 5:
				return new Circle(circle,circle05);
			case 6:
				return new Circle(circle,circle06);
			case 7:
				return new Circle(circle,circle07);
			case 8:
				return new Circle(circle,circle08);
			case 9:
				return new Circle(circle,circle09);
			case 10:
				return new Circle(circle,circle10);	
			}
		}else{
			return new Circle(circle);
		}
		return null;
	
	}

	/**
	 * Inits the game iniciamos parametros de juego como son la scores, playing y paused.
	 */
	void initGame(){
		score = 0;
		playing = true;
		paused = false;

	}
	
	/**
	 * Calculate bpm calcula el tempo de la cancion elegida por el usuario.
	 *
	 * @param path the path se le pasa la ruta de acceso a la cancion elegida por el usuario
	 */
	private void calculateBPM(String path) {
		int numbpm=0;
		try {
			es.drOsu.common.Song song = new es.drOsu.common.Song(path);
			//mirar bpm
			boolean trace = false;
			EchoNestAPI en = new EchoNestAPI(Constants.keyEchoNest);
			en.setTraceSends(trace);
            en.setTraceRecvs(trace);
            en.setMinCommandTime(0);
            SongParams p = new SongParams();
            p.setArtist(song.artist);
            p.setTitle(song.title);
            p.setResults(1);
            p.includeAudioSummary();
            List<Song> songs = en.searchSongs(p);
            if (songs.size() > 0) {
            	if(Tools.checkConnectivity(mContex)){
	            	do{
	            		bpm =(int) songs.get(0).getTempo();
	            		numbpm++;
	            	}while(bpm==0 && numbpm<6);
	            	if(numbpm==6 || bpm==0){
	    				errorbpm=true;   	    				      		
	            	}
            	}
                Log.d(TAG, "artista: "+song.artist+" titulo: "+song.title+" bpm: "+bpm);
            } else {
                Log.d(TAG, "error al obtener los bpm");
            }
            
		} catch (EchoNestException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/* (non-Javadoc)
	 * @see es.drOsu.game.GameNew#gameOver()
	 */
	@Override
	protected boolean gameOver() {
		return loaded && !playing;
	}
	
	/* (non-Javadoc)
	 * @see es.drOsu.game.GameNew#getScore()
	 */
	@Override
	protected long getScore() {
		return score;
	}
	
	/* (non-Javadoc)
	 * @see android.view.View#onDraw(android.graphics.Canvas)
	 */
	@Override
	protected void onDraw(Canvas canvas){
		if(freememory==false){
			if(game){
				setBackgroundResource(R.drawable.drosuwallpaper);
				lifeBar.draw(canvas);
				
				canvas.drawText(""+getScore(),getWidth(), black.getTextSize(), black);
				canvas.drawText("x"+maxLengthCombo, black.getTextSize()*2*mContex.getResources().getDisplayMetrics().density,getHeight()-(5*mContex.getResources().getDisplayMetrics().density),black);
				for(int i=path.size()-1;i>=0;i--){
					if(path.get(i).getClass().getName().compareTo(CIRCLE)==0){
						Circle c = (Circle) path.get(i);
						if(firsttimedraw && i==0){
							c.active=true;
							c.sliderActive=true;
							//c.draw(canvas, red, i+1, black);
							if(graphicsEffects){
								c.draw(canvas,approachcircleDrawable.get(c.tick));
							}else{
								c.draw(canvas, violetCircle, i+1, whiteText,violetSlider);
							}
							firsttimedraw=false;
							path.set(i, c);
						}else{
							//c.draw(canvas, red, i+1, black);
							if(graphicsEffects){
								c.draw(canvas,approachcircleDrawable.get(c.tick));
							}else{
								c.draw(canvas, violetCircle, i+1, whiteText,violetSlider);
							}
						}
					}
					if(path.get(i).getClass().getName().compareTo(DRAG)==0){
						Drag d = (Drag) path.get(i);
						if(firsttimedraw && i==0){
							d.active=true;
							if(graphicsEffects)
								d.draw(canvas, red, black, green,approachcircleDrawable.get(d.tick),ball[d.tickBall]);
							else
								d.draw(canvas, violetCircle, green, i+1, whiteText, violetSlider, greenSlider, ball[d.tickBall]);
							
							//d.draw(canvas, red, green, i+1, black, sliderfollowcircleDrawables.get(d.tick));
							firsttimedraw=false;
							path.set(i,d);
						}else{
							//d.draw(canvas, red, green, i+1, black);
							if(d.tick<9){
								try{
								//Log.d(TAG, "tickball draw"+d.tickBall);
								if(graphicsEffects)
									d.draw(canvas, red, black, green,approachcircleDrawable.get(d.tick),ball[d.tickBall]);
								else
									d.draw(canvas, violetCircle, green, i+1, whiteText, violetSlider, greenSlider ,ball[d.tickBall]);
								//d.draw(canvas, red, green, i+1, black, sliderfollowcircleDrawables.get(d.tick));
								}catch (Exception e) {
									// TODO: handle exception
								}
							}
						}
					}
				}
				
				
				if(hit50.active){
					if(soundsEffects)
						mp.start();
					hit50.drawHit(canvas);
					hit50.active=false;
				
				}
				
				if(hit100.active){
					if(soundsEffects)
						mp.start();
					hit100.drawHit(canvas);
					hit100.active=false;
					
				}
					
				if(hit300.active){
					if(soundsEffects)
						mp.start();
					hit300.drawHit(canvas);
					hit300.active=false;
				}
				if(fail.active){
					if(soundsEffects)
						mpfail.start();
					fail.drawHit(canvas);
					fail.active=false;
					
				}
				if(hit100bonus.active){
					if(soundsEffects)
						mp.start();
					hit100bonus.drawHit(canvas);
					hit100bonus.active=false;
					
				}
				if(hit300bonus.active){
					if(soundsEffects)
						mp.start();
					hit300bonus.drawHit(canvas);
					hit300bonus.active=false;
					
					
				}
				if(hit300extraBonus.active){
					if(soundsEffects)
						mp.start();
					hit300extraBonus.drawHit(canvas);
					hit300extraBonus.active=false;
					
				}
			}
			if(countdown){
				if(numberCountDown<3){
					blue_countdown.setTextSize((width/3)/(numberCountDown+1));
					canvas.drawText("3", (width/4), (float) (height/1.75), blue_countdown);
				}
				if(numberCountDown>=3 && numberCountDown<6){
					blue_countdown.setTextSize((width/3)/(numberCountDown-2));
					canvas.drawText("2", (width/2), (float) (height/1.75), blue_countdown);
				}
				if(numberCountDown>=6 && numberCountDown<9){
					blue_countdown.setTextSize((width/3)/(numberCountDown-5));
					canvas.drawText("1", (3*width/4), (float) (height/1.75), blue_countdown);
				}
				if(numberCountDown==9){
					blue_countdown.setTextSize(width/3);
					canvas.drawText("GO!", width/4, (float) (height/1.75), blue_countdown);
				}
				/*countDownDrawable[numberCountDown].setBounds(0, 0, countDownDrawable[numberCountDown].getIntrinsicWidth(), countDownDrawable[numberCountDown].getIntrinsicHeight());
				countDownDrawable[numberCountDown].draw(canvas);*/
			}
			if(shakebar){
				setBackgroundResource(R.drawable.shake_bar_wallpaper);
				stopY -=(int) Math.abs(mAccelerometerValues[1]);
				if(stopY > (int)((startY-background_bar.getIntrinsicHeight())/mContex.getResources().getDisplayMetrics().density)){//(height/4)){
	    			//canvas.drawRect(startX, startY, stopX, shakebarView.getHeight()- stopY, green);    			
	    			pink_bar.setBounds(startX, (int)((startY-pink_bar.getIntrinsicHeight())/mContex.getResources().getDisplayMetrics().density), startX+pink_bar.getIntrinsicWidth(),startY);
	    			pink_bar.draw(canvas);
	    			//canvas.drawRect(startX, startY-(startY-stopY), startX+background_bar.getIntrinsicWidth(), startY, green);
	    			RectF rect = new RectF(startX, stopY, startX+background_bar.getIntrinsicWidth(), startY);
	    			canvas.drawRoundRect(rect, 8, 8, dark_pink_bar);
	    			
	    			background_bar.setBounds(startX, (int)((startY-background_bar.getIntrinsicHeight())/mContex.getResources().getDisplayMetrics().density), startX+background_bar.getIntrinsicWidth(), startY);
	    			background_bar.draw(canvas);
	    		}else{
	    			Toast.makeText(mContex, mContex.getResources().getString(R.string.gotcha), Toast.LENGTH_SHORT).show();
	    			stopY= startY;//(int) (startY-mContex.getResources().getDisplayMetrics().density);
	    			score+=1000;
	    		}
			}
			if(orientation){
				canvas.drawRect(0, 0, width, height, white);
				compass=null;
				compass=Tools.resizeImage(mContex, R.drawable.compass, getHeight(), getHeight(), true, (int) (90-mOrientationValues[0]));//el 90 es para que indique el norte
	    		//Log.d(TAG, "grados: "+(360-mOrientationValues[0]));
	    		compass.setBounds((int)selX - compass.getIntrinsicWidth()*3/4, (int)selY - compass.getIntrinsicHeight()*3/4,(int) selX+compass.getIntrinsicWidth()*3/4, (int) selY+compass.getIntrinsicHeight()*3/4);
	            compass.draw(canvas);
	            canvas.drawLine(selX, selY, (stopOX + (Constants.maxLengthLine*(float)Math.cos(Math.toRadians(360-mOrientationValues[0])))) , (stopOY +(Constants.maxLengthLine*(float)Math.sin(Math.toRadians(360-mOrientationValues[0])))), blackorientation);
	    		canvas.drawLine(selX, selY, (stopOX + (Constants.maxLengthLine*(float)Math.cos(Math.toRadians(360-degrees)))) , (stopOY +(Constants.maxLengthLine*(float)Math.sin(Math.toRadians(360-degrees)))), degreesPaint);
	    		
	    		if ((degrees-3*mContex.getResources().getDisplayMetrics().density) <= mOrientationValues[0] && (degrees+3*mContex.getResources().getDisplayMetrics().density) >= mOrientationValues[0]){
	    			Toast.makeText(mContex, mContex.getResources().getString(R.string.gotcha), Toast.LENGTH_SHORT).show();
	    			score+=1000;
	    			degrees = (float)Math.random()*360;
	    		}
			}
		}
	}


	/* (non-Javadoc)
	 * @see android.view.View#onTouchEvent(android.view.MotionEvent)
	 */
	@Override
	public boolean onTouchEvent(MotionEvent motionEvent){
		if(number<path.size()){
			if(motionEvent.getAction() == MotionEvent.ACTION_MOVE && path.get(number).getClass().getName().compareTo(DRAG)==0) {
				lifeBar.tick--;
				Drag drag = (Drag) path.get(number);
				if(!drag.sliderActive)
					drag.ballActive=true;
				
				path.set(number, drag);
				//this.setUpdateTimer(100);
				//startUpdateTimer();
				RectF oval = new RectF(drag.coorXstart,drag.coorYstart,drag.coorXend,drag.coorYend);
				if(firstDragMotionEvent)
				{
					firstDragMotionEvent=false;
					xMotionEvent = motionEvent.getX();
					yMotionEvent = motionEvent.getY();
				}
				
				if(oval.left>oval.right && oval.bottom>oval.top){
					if(xMotionEvent>=motionEvent.getX() && yMotionEvent<=motionEvent.getY()){
						if(oval.left+drag.radius >= motionEvent.getX() && motionEvent.getX() > oval.right && oval.bottom+drag.radius >= motionEvent.getY() && motionEvent.getY() > oval.top )
						{
							score += 20;
						}
					}
					
				}
				if(oval.left>oval.right && oval.top>oval.bottom){
					if(xMotionEvent>=motionEvent.getX() && yMotionEvent>=motionEvent.getY()){
						if(oval.left+drag.radius >= motionEvent.getX() && motionEvent.getX() > oval.right && oval.top+drag.radius >= motionEvent.getY() && motionEvent.getY() > oval.bottom )
						{
							score += 20;
						}
					}
				}
				if(oval.right>oval.left && oval.top>oval.bottom){
					if(xMotionEvent<=motionEvent.getX() && yMotionEvent>=motionEvent.getY()){
						if(oval.right+drag.radius >= motionEvent.getX() && motionEvent.getX() > oval.left && oval.top+drag.radius >= motionEvent.getY() && motionEvent.getY() > oval.bottom )
						{
							score += 20;
						}
					}
				}
				if(oval.right>oval.left && oval.bottom>oval.top){
					if(xMotionEvent<=motionEvent.getX() && yMotionEvent<=motionEvent.getY()){
						if(oval.right+drag.radius >= motionEvent.getX() && motionEvent.getX() > oval.left && oval.bottom+drag.radius >= motionEvent.getY() && motionEvent.getY() > oval.top )
						{
							score += 20;
						}
					}
				}
				if(drag.tickBall==Constants.maxTicksBall-1){
					if((drag.coorXball-(drag.radius/2)) < xMotionEvent && xMotionEvent < (drag.coorXball+(drag.radius/2)) && 
							(drag.coorYball-(drag.radius/2)) < yMotionEvent && yMotionEvent < (drag.coorYball+(drag.radius/2))){
						firstDragMotionEvent=true;
						stopUpdateTimer();
						setUpdateTimer(timeTimer);
						startUpdateTimer();
						maxLengthCombo++;
						score += 300*maxLengthCombo;
						combo300++;
						count300++;
						if(number==9 && combo300==10){
							score+=300*maxLengthCombo;
							count300Bonus++;
							hit300extraBonus.setXY(drag.coorXend, drag.coorYend);
							hit300extraBonus.active=true;
						}else{
							if(number==9 && combo300>6){
								score+=150*maxLengthCombo;
								count300Beat++;
								hit300bonus.setXY(drag.coorXend, drag.coorYend);
								hit300bonus.active=true;
							}else{
								hit300.setXY(drag.coorXend, drag.coorYend);
								hit300.active=true;
							}
						}
						drag.active=false;
						path.set(number, drag);
						if(number<path.size()-1){
							if(path.get(number+1).getClass().getName().compareTo(CIRCLE)==0){
								Circle c = (Circle) path.get(number+1);
								if(c.active==false){
									c.active=true;
									c.sliderActive=true;
									c.tick++;
									path.set(number+1, c);
								}
								
							}else{
								if(path.get(number+1).getClass().getName().compareTo(DRAG)==0){
									Drag d = (Drag) path.get(number+1);
									d.active=true;
									d.sliderActive=true;
									d.tick++;
									path.set(number+1, d);
								}
							}
						}
						number++;
					}					
				}
				xMotionEvent=motionEvent.getX();
				yMotionEvent=motionEvent.getY();
				
			}else{
				if(number<path.size()){
					if(motionEvent.getAction() == MotionEvent.ACTION_DOWN && path.get(number).getClass().getName().compareTo(CIRCLE)==0){
						lifeBar.tick-=5;
						Circle circles = (Circle) path.get(number);
				        if ((circles.coorX + circles.radius) > motionEvent.getX() && motionEvent.getX() > (circles.coorX - circles.radius) && 
				        		(circles.coorY + circles.radius) > motionEvent.getY() && motionEvent.getY() > (circles.coorY - circles.radius))
						{
							switch (circles.tick) {
								case 8:
								case 7:
									maxLengthCombo++;
									score += 300*maxLengthCombo;
									combo300++;
									count300++;
									if(number==9 && combo300==10){
										score+=300*maxLengthCombo;
										count300Bonus++;
										hit300extraBonus.setXY(circles.coorX, circles.coorY);
										hit300extraBonus.active=true;
									}else{
										if(number==9 && combo300>6){
											score+=150*maxLengthCombo;
											count300Beat++;
											hit300bonus.setXY(circles.coorX, circles.coorY);
											hit300bonus.active=true;
										}else{
											hit300.setXY(circles.coorX, circles.coorY);
											hit300.active=true;
										}
									}
									break;								
								case 5:
								case 6:
									maxLengthCombo++;
									score += 100*maxLengthCombo;
									count100++;
									combo100++;
									if(number==9 && combo100>6){
										score+=100*maxLengthCombo;
										count100Bonus++;
										hit100bonus.setXY(circles.coorX, circles.coorY);
										hit100bonus.active=true;
									}else{
										hit100.setXY(circles.coorX, circles.coorY);
										hit100.active=true;
									}
									break;
								case 4:
									maxLengthCombo++;
									score += 50*maxLengthCombo;
									count50++;							
									hit50.setXY(circles.coorX, circles.coorY);
									hit50.active=true;
									break;
									
							}
							if(circles.tick>=4){
								circles.active = false;
							
								path.set(number, circles);
								if(number<path.size()-1){
									if(path.get(number+1).getClass().getName().compareTo(CIRCLE)==0){
										Circle c = (Circle) path.get(number+1);
										if(c.active==false){
											c.active=true;
											c.sliderActive=true;
											c.tick++;
											path.set(number+1, c);
										}
										
									}else{
										if(path.get(number+1).getClass().getName().compareTo(DRAG)==0){
											Drag d = (Drag) path.get(number+1);
											d.active=true;
											d.sliderActive=true;
											d.tick++;
											path.set(number+1, d);
										}
									}
								}
								number++;
							}
						}
					}
					//if(motionEvent.getAction() == MotionEvent.ACTION_UP && path.get(number).getClass().getName().compareTo(DRAG)==0) {
						/*lifeBar.tick-=5;
						
						Drag drag = (Drag) path.get(number);
						if(!drag.sliderActive){
							RectF oval = new RectF(drag.coorXstart,drag.coorYstart,drag.coorXend,drag.coorYend);
							firstDragMotionEvent=true;
							stopUpdateTimer();
							setUpdateTimer(timeTimer);
							startUpdateTimer();
							if((drag.coorXend + drag.radius) > motionEvent.getX() && motionEvent.getX() > (drag.coorXend - drag.radius) && 
								(drag.coorYend + drag.radius) > motionEvent.getY() && motionEvent.getY() > (drag.coorYend - drag.radius)){
								
								if( (drag.coorXball + drag.radius) > motionEvent.getX() && motionEvent.getX() > (drag.coorXball - drag.radius) &&
									(drag.coorYball + drag.radius) > motionEvent.getY() && motionEvent.getY() > (drag.coorYball - drag.radius)){
									maxLengthCombo++;
									score += 300*maxLengthCombo;
									combo300++;
									count300++;
									if(number==9 && combo300==10){
										score+=300*maxLengthCombo;
										count300Bonus++;
										hit300extraBonus.setXY(drag.coorXend, drag.coorYend);
										hit300extraBonus.active=true;
									}else{
										if(number==9 && combo300>6){
											score+=150*maxLengthCombo;
											count300Beat++;
											hit300bonus.setXY(drag.coorXend, drag.coorYend);
											hit300bonus.active=true;
										}else{
											hit300.setXY(drag.coorXend, drag.coorYend);
											hit300.active=true;
										}
									}
									drag.active=false;
									path.set(number, drag);
									if(number<path.size()-1){
										if(path.get(number+1).getClass().getName().compareTo(CIRCLE)==0){
											Circle c = (Circle) path.get(number+1);
											if(c.active==false){
												c.active=true;
												c.sliderActive=true;
												c.tick++;
												path.set(number+1, c);
											}
											
										}else{
											if(path.get(number+1).getClass().getName().compareTo(DRAG)==0){
												Drag d = (Drag) path.get(number+1);
												d.active=true;
												d.sliderActive=true;
												d.tick++;
												path.set(number+1, d);
											}
										}
									}
									number++;
								}
							}else{
								if(oval.left>oval.right && oval.bottom>oval.top){
									if(oval.left+drag.radius >= motionEvent.getX() && motionEvent.getX() > oval.right && 
											oval.bottom+drag.radius >= motionEvent.getY() && motionEvent.getY() > oval.top )
									{
										maxLengthCombo++;
										score += 100*maxLengthCombo;									
										count100++;
										combo100++;							
										if(number==9 && combo100>6){
											score+=100*maxLengthCombo;
											count100Bonus++;
											hit100bonus.setXY(drag.coorXend, drag.coorYend);
											hit100bonus.active=true;
										}else{
											hit100.setXY(drag.coorXend, drag.coorYend);
											hit100.active=true;
										}
									}else{
										if(drag.tick>4 && drag.sliderActive){
											score -=300;
											countFail++;
											saveMaxLengthCombo();
											maxLengthCombo=0;
											fail.setXY(drag.coorXend, drag.coorYend);
											fail.active=true;
											drag.active=false;
											path.set(number, drag);
											if(number<path.size()-1){
												if(path.get(number+1).getClass().getName().compareTo(CIRCLE)==0){
													Circle c = (Circle) path.get(number+1);
													if(c.active==false){
														c.active=true;
														c.sliderActive=true;
														c.tick++;
														path.set(number+1, c);
													}
													
												}else{
													if(path.get(number+1).getClass().getName().compareTo(DRAG)==0){
														Drag d = (Drag) path.get(number+1);
														d.active=true;
														d.sliderActive=true;
														d.tick++;
														path.set(number+1, d);
													}
												}
											}
											number++;
										}
									}
								}
								if(oval.left>oval.right && oval.top>oval.bottom){
									if(oval.left+drag.radius >= motionEvent.getX() && motionEvent.getX() > oval.right && 
											oval.top+drag.radius >= motionEvent.getY() && motionEvent.getY() > oval.bottom )
									{
										maxLengthCombo++;
										score += 100*maxLengthCombo;
										count100++;
										combo100++;									
										if(number==9 && combo100>6){
											score+=100*maxLengthCombo;
											count100Bonus++;
											hit100bonus.setXY(drag.coorXend, drag.coorYend);
											hit100bonus.active=true;
										}else{
											hit100.setXY(drag.coorXend, drag.coorYend);
											hit100.active=true;
										}
									}else{
										if(drag.tick>4 && drag.sliderActive){
											score -=300;
											countFail++;
											maxLengthCombo=0;
											fail.setXY(drag.coorXend, drag.coorYend);
											fail.active=true;
											drag.active=false;
											path.set(number, drag);
											if(number<path.size()-1){
												if(path.get(number+1).getClass().getName().compareTo(CIRCLE)==0){
													Circle c = (Circle) path.get(number+1);
													if(c.active==false){
														c.active=true;
														c.sliderActive=true;
														c.tick++;
														path.set(number+1, c);
													}
													
												}else{
													if(path.get(number+1).getClass().getName().compareTo(DRAG)==0){
														Drag d = (Drag) path.get(number+1);
														d.active=true;
														d.sliderActive=true;
														d.tick++;
														path.set(number+1, d);
													}
												}
											}
											number++;
										}
									}
								}
								if(oval.right>oval.left && oval.top>oval.bottom){
									if(oval.right+drag.radius >= motionEvent.getX() && motionEvent.getX() > oval.left && 
											oval.top+drag.radius >= motionEvent.getY() && motionEvent.getY() > oval.bottom )
									{
										maxLengthCombo++;
										score += 100*maxLengthCombo;
										count100++;
										combo100++;	
										if(number==9 && combo100>6){
											score+=100*maxLengthCombo;
											count100Bonus++;
											hit100bonus.setXY(drag.coorXend, drag.coorYend);
											hit100bonus.active=true;
										}else{
											hit100.setXY(drag.coorXend, drag.coorYend);
											hit100.active=true;
										}
									}else{
										if(drag.tick>4 && drag.sliderActive){
											score -=300;
											countFail++;
											maxLengthCombo=0;
											fail.setXY(drag.coorXend, drag.coorYend);
											fail.active=true;
											drag.active=false;
											path.set(number, drag);
											if(number<path.size()-1){
												if(path.get(number+1).getClass().getName().compareTo(CIRCLE)==0){
													Circle c = (Circle) path.get(number+1);
													if(c.active==false){
														c.active=true;
														c.sliderActive=true;
														c.tick++;
														path.set(number+1, c);
													}
													
												}else{
													if(path.get(number+1).getClass().getName().compareTo(DRAG)==0){
														Drag d = (Drag) path.get(number+1);
														d.active=true;
														d.sliderActive=true;
														d.tick++;
														path.set(number+1, d);
													}
												}
											}
											number++;
										}
									}
								}
								if(oval.right>oval.left && oval.bottom>oval.top){
									if(oval.right+drag.radius >= motionEvent.getX() && motionEvent.getX() > oval.left && 
											oval.bottom+drag.radius >= motionEvent.getY() && motionEvent.getY() > oval.top )
									{
										maxLengthCombo++;
										score += 100*maxLengthCombo;
										count100++;
										combo100++;
										if(number==9 && combo100>6){
											score+=100*maxLengthCombo;
											count100Bonus++;
											hit100bonus.setXY(drag.coorXend, drag.coorYend);
											hit100bonus.active=true;
										}else{
											hit100.setXY(drag.coorXend, drag.coorYend);
											hit100.active=true;
										}
									}else{
										if(drag.tick>4 && drag.sliderActive){
											score -=300;
											countFail++;
											maxLengthCombo=0;
											fail.setXY(drag.coorXend, drag.coorYend);
											fail.active=true;
											drag.active=false;
											path.set(number, drag);
											if(number<path.size()-1){
												if(path.get(number+1).getClass().getName().compareTo(CIRCLE)==0){
													Circle c = (Circle) path.get(number+1);
													if(c.active==false){
														c.active=true;
														c.sliderActive=true;
														c.tick++;
														path.set(number+1, c);
													}
													
												}else{
													if(path.get(number+1).getClass().getName().compareTo(DRAG)==0){
														Drag d = (Drag) path.get(number+1);
														d.active=true;
														d.sliderActive=true;
														d.tick++;
														path.set(number+1, d);
													}
												}
											}
											number++;
										}
									}
								}
							}
						}*/
					//}else{
						/*else
							{
								score -= 300;
								countFail++;
								maxLengthCombo=0;
								fail.setXY(circles.coorX, circles.coorY);
								fail.active=true;
								circles.active = false;
								path.set(number, circles);
								//comprobar y cargar el siguiente si este no esta activo.
								if(number<path.size()-1){
									if(path.get(number+1).getClass().getName().compareTo(CIRCLE)==0){
										Circle c = (Circle) path.get(number+1);
										if(c.active==false){
											c.active=true;
											c.sliderActive=true;
											c.tick++;
											path.set(number+1, c);
										}
										
									}else{
										if(path.get(number+1).getClass().getName().compareTo(DRAG)==0){
											Drag d = (Drag) path.get(number+1);
											d.active=true;
											d.sliderActive=true;
											d.tick++;
											path.set(number+1, d);
										}
									}
								}
								number++;
							}*/
				}
			}
		}
        return true;
	}

	/**
	 * Save max length combo guarda el numero de aciertos consecutivos maximos conseguido por un jugador.
	 */
	private void saveMaxLengthCombo() {
		if(maxLengthComboFinal<maxLengthCombo){
			maxLengthComboFinal=maxLengthCombo;
		}		
	}
	
	/* (non-Javadoc)
	 * @see es.drOsu.game.GameNew#updateGame()
	 */
	@Override
	protected void updateGame() {
		if(countdown){
			numberCountDown++;
			
			if(numberCountDown==3){
				mpcountdown.start();
			}
			if(numberCountDown>9){
				if(firsttime){
					if(!bpmCalculated){
						try {
							//Log.d(TAG,"Entra");
							calculateBPM(musicPath);
							if(!errorbpm){
								Log.d(TAG, "bmp: "+bpm);
								double seg=60/bpm;
								//Log.d(TAG, "seg: "+seg);
								stopUpdateTimer();
								if(gameDifficulty==Constants.CHAMPION){
									timeTimer = (long)((1000*seg/2));
								}
								if(gameDifficulty==Constants.MEDIUM){
									timeTimer = (long)((1000*seg/1.5));
								}
								if(gameDifficulty==Constants.EASY){
									timeTimer = (long)((1000*seg));
								}
								setUpdateTimer(timeTimer);
								//Log.d(TAG, "bpm: "+bpm+" timer:"+timeTimer);
								
								Music.play(mContex, musicPath);
								pathIteration = Music.duration(musicPath);
								//Log.d(TAG, "pathiterator: "+pathIteration);
								startUpdateTimer();
								firsttime=false;
							}else{
								halt();
								Intent intentMain = new Intent(mContex, DrosuMain.class);
								paused=true;
								firsttime=true;
								resume();
								mContex.startActivity(intentMain);
							}
						} catch (IllegalArgumentException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (IllegalStateException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
							updateGame();
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}else{
						Log.d(TAG, "bpm calculados");
						stopUpdateTimer();
						setUpdateTimer(timeTimer);
						try {
							Music.play(mContex, musicPath);
							pathIteration = Music.duration(musicPath);
						} catch (IllegalArgumentException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (IllegalStateException e) {
							e.printStackTrace();
						} catch (IOException e) {
							e.printStackTrace();
						}
						startUpdateTimer();
						firsttime=false;
					}
				}
				if(!errorbpm){
					countdown=false;
					game=true;
					Log.d(TAG, "cambia a juego");
				}
			}
		}
		if(shakebar){
			if(Music.currentPosition()>(pathIteration*2/3+timeTimer*40)){
				game=true;
				shakebar=false;
				mSensorManager.unregisterListener(this);
			}
		}
		if(orientation){
			if(Music.currentPosition()>(pathIteration/3+timeTimer*40)){
				game=true;
				orientation=false;
				//mSensorManager.unregisterListener(this);
			}
		}
		if(game){
		
			//Log.d(TAG, "current: "+Music.currentPosition());
			if((pathIteration/3)<Music.currentPosition() && Music.currentPosition()<pathIteration/3+timeTimer){
				Log.d(TAG, "bonus brujula");
				sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
		    	for (Sensor sensor : sensorList)
		    		mSensorManager.registerListener(this, sensor,SensorManager.SENSOR_DELAY_NORMAL);
				orientation=true;
				game = false;
			}
			if((pathIteration*2/3)<Music.currentPosition() && Music.currentPosition()<pathIteration*2/3+timeTimer){
				Log.d(TAG, "bonus shackebar");
				shakebar=true;
				game = false;
			}
			lifeBar.tick++;
			if(lifeBar.tick<0){
				lifeBar.tick=0;			
			}
			lifeBar.updateBar();
			
			
			
			if(number<10){
				if(path.get(number).getClass().getName().compareTo(CIRCLE)==0){
					Circle circles=(Circle) path.get(number);
					circles.tick++;
					path.set(number, circles);
					int i = number;
					while(circles.tick>3 && i<9 && path.get(i+1).getClass().getName().compareTo(CIRCLE)==0){
						Circle c = (Circle) path.get(i+1);
						c.active=true;
						c.sliderActive=true;
						c.tick++;
						path.set(i+1, c);
						i++;
						if(i<9)
							circles=(Circle) path.get(i);
						
					}
					if(number<path.size()-1){
						circles=(Circle) path.get(number);
						if(circles.tick>3 && path.get(number+1).getClass().getName().compareTo(DRAG)==0){
							Drag d=(Drag) path.get(number+1);
							d.active=true;
							d.sliderActive=true;
							d.tick++;
							path.set(number+1, d);
						}
					}						
					circles=(Circle) path.get(number);
					if(circles.tick>=circles.maxTick){
						score-=300;
						circles.active=false;
						countFail++;
						maxLengthCombo=0;
						fail.setXY(circles.coorX, circles.coorY);
						fail.active=true;
						path.set(number, circles);
						number++;
					}
				}else{
					if(path.get(number).getClass().getName().compareTo(DRAG)==0){
						Drag drag=(Drag) path.get(number);
						if(drag.sliderActive==true){
							drag.tick++;
							
							path.set(number, drag);
							if(drag.tick>=drag.maxTick){
								drag.sliderActive=false;
								drag.ballActive=true;
								if(soundsEffects)
									mpdrag.start();
								stopUpdateTimer();
								setUpdateTimer(timeTimer*2/5);
								startUpdateTimer();
								path.set(number, drag);
								/*drag=(Drag) path.get(number);
								score-=300;
								drag.active=false;
								countFail++;
								maxLengthCombo=0;
								fail.setXY(drag.coorXstart, drag.coorYstart);
								fail.active=true;
								path.set(number, drag);
								if(number<path.size()-1){
									if(path.get(number+1).getClass().getName().compareTo(DRAG)==0){
										Drag d=(Drag) path.get(number+1);
										d.active=true;
										d.sliderActive=true;
										d.tick++;
										path.set(number+1, d);
									}else{
										if(path.get(number+1).getClass().getName().compareTo(CIRCLE)==0){
											Circle c=(Circle) path.get(number+1);
											c.active=true;
											c.sliderActive=true;
											c.tick++;
											path.set(number+1, c);
										}
									}
								}	
								number++;*/
								
							}
						}
						if(number<10 && path.get(number).getClass().getName().compareTo(DRAG)==0){
							drag=(Drag) path.get(number);
							if(drag.ballActive==true){
								drag.tickBall++;
								//Log.d(TAG, "ticksball:" + drag.tickBall);
								path.set(number, drag);
								if(drag.tickBall>=drag.maxTickBall){
									stopUpdateTimer();
									setUpdateTimer(timeTimer);
									startUpdateTimer();
									drag=(Drag) path.get(number);
									score-=300;
									drag.active=false;
									countFail++;
									maxLengthCombo=0;
									fail.setXY(drag.coorXend, drag.coorYend);
									fail.active=true;
									path.set(number, drag);
									if(number<path.size()-1){
										if(path.get(number+1).getClass().getName().compareTo(DRAG)==0){
											Drag d=(Drag) path.get(number+1);
											d.active=true;
											d.sliderActive=true;
											d.tick++;
											path.set(number+1, d);
										}else{
											if(path.get(number+1).getClass().getName().compareTo(CIRCLE)==0){
												Circle c=(Circle) path.get(number+1);
												c.active=true;
												c.sliderActive=true;
												c.tick++;
												path.set(number+1, c);
											}
										}
									}								
									number++;
								}
							}
						}
					}
				}
			}else{
				saveMaxLengthCombo();
				if(gameMode==Constants.HARDCORE)
					generatePath(getWidth(),getHeight());
				else{
					numberNormal+=10;
					path=new ArrayList<Object>();
					for(int i=numberNormal;i<numberNormal+10;i++){
						path.add(pathReadedFile.get(i));
					}
				}
				firsttimedraw=true;
				number=0;
				combo100=0;
				combo300=0;
			}
			if(lifeBar.tick>=lifeBar.maxTick){
				Music.stop(mContex);
				halt();
				paused=true;
				Intent intent = new Intent(mContex, Scores.class);
				Bundle bundle = new Bundle();
				bundle.putInt(Constants.keyScore, (int) getScore());
				saveMaxLengthCombo();
				bundle.putInt(Constants.keyMaxCombo,maxLengthComboFinal);
				bundle.putInt(Constants.keyHit50, count50);
				bundle.putInt(Constants.keyHit100, count100);
				bundle.putInt(Constants.keyBonusHit100, count100Bonus);
				bundle.putInt(Constants.keyHit300, count300);
				bundle.putInt(Constants.keyBonusHit300, count300Bonus);
				bundle.putInt(Constants.keyBeatHit300, count300Beat);
				bundle.putInt(Constants.keyFail, countFail);
				bundle.putString(Constants.keyPath, musicPath);
				bundle.putInt(Constants.keyGameMode, gameMode);
				bundle.putInt(Constants.keyGameDifficulty,gameDifficulty);
				bundle.putString(Constants.keyUser, user);
				bundle.putInt(Constants.keyDuration, pathIteration);
				intent.putExtras(bundle);
				game=false;				
				//gameOver();
				freeMemory();
				firsttime=true;
				mContex.startActivity(intent);
				
				//Log.d(TAG, "inicia socores xq no hay vida"+" ticks: "+lifeBar.tick);
				try {
					finalize();
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			
			try{
				if(Music.currentPosition()+500>Music.duration(musicPath)){
					Music.stop(mContex);
					halt();
					Intent intent = new Intent(mContex, Scores.class);
					Bundle bundle = new Bundle();
					bundle.putInt(Constants.keyScore, (int) getScore());
					saveMaxLengthCombo();
					bundle.putInt(Constants.keyMaxCombo,maxLengthComboFinal);
					bundle.putInt(Constants.keyHit50, count50);
					bundle.putInt(Constants.keyHit100, count100);
					bundle.putInt(Constants.keyBonusHit100, count100Bonus);
					bundle.putInt(Constants.keyHit300, count300);
					bundle.putInt(Constants.keyBonusHit300, count300Bonus);
					bundle.putInt(Constants.keyBeatHit300, count300Beat);
					bundle.putInt(Constants.keyFail, countFail);
					bundle.putString(Constants.keyPath, musicPath);
					bundle.putInt(Constants.keyGameMode, gameMode);
					bundle.putInt(Constants.keyGameDifficulty,gameDifficulty);
					bundle.putString(Constants.keyUser, user);
					bundle.putInt(Constants.keyDuration, pathIteration);
					intent.putExtras(bundle);
					paused=true;
					game=false;
					freeMemory();
					firsttime=true;
					mContex.startActivity(intent);
				}
			}catch (Exception e) {
				Log.d(TAG, "error music end");
			}
		}
		
	}

	/**
	 * Free memory libera de la memoria todos los elementos utilizados en este vista.
	 */
	public void freeMemory() {
		freememory=true;
		//path=null;
		hit50=null;
		hit100=null;
		hit300=null;
		hit100bonus=null;
		hit300bonus=null;
		hit300extraBonus=null;
		fail=null;
		mp.release();
		mpdrag.release();
		mpcountdown.release();
		mpfail.release();
		lifeBar=null;
		circle01=null;
		circle02=null;
		circle03=null;
		circle04=null;
		circle05=null;
		circle06=null;
		circle07=null;
		circle08=null;
		circle09=null;
		circle10=null;
		if(graphicsEffects){
			sliderfollowcircle.recycle();
			approachcircle.recycle();
			approachcircleDrawable.removeAll(approachcircleDrawable);
			sliderfollowcircleDrawables.removeAll(sliderfollowcircleDrawables);
		}
		ballStart.recycle();
		
		ball=null;
		
		red.reset();
		black.reset();
		blackorientation.reset();
		degreesPaint.reset();
		white.reset();
		green.reset();
		background_bar=null;
		pink_bar=null;
		dark_pink_bar=null;
		compass=null;
		if(pathReadedFile!=null)
			pathReadedFile.removeAll(pathReadedFile);
	}

	/* (non-Javadoc)
	 * @see android.view.View#onKeyDown(int, android.view.KeyEvent)
	 */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		// TODO Auto-generated method stub
		
		switch (keyCode) {
			case KeyEvent.KEYCODE_MENU:
			case KeyEvent.KEYCODE_BACK:
				if(countdown==false)
					Music.pause(mContex);
				
				halt();
	
				dialog = new Dialog(mContex);
				dialog.setContentView(R.layout.pausemenu);
				dialog.setTitle(mContex.getResources().getString(R.string.pause_menu_text));
				dialog.setOnDismissListener(new OnDismissListener() {
					
					@Override
					public void onDismiss(DialogInterface arg0) {
						// TODO Auto-generated method stub
						resume();
					}
				});
				Typeface face=Typeface.createFromAsset(mContex.getAssets(), "fonts/BILLD.TTF");
				
				Button retryButton = (Button) dialog.findViewById(R.id.Button_Menu_Pause_Retry);
			    retryButton.setTypeface(face);
			    retryButton.setOnClickListener(this);
			    
			    Button continueButton = (Button) dialog.findViewById(R.id.Button_Menu_Pause_Choose);
			    continueButton.setTypeface(face);
			    continueButton.setOnClickListener(this);
			    
			    Button mainButton = (Button) dialog.findViewById(R.id.Button_Menu_Pause_Main);
			    mainButton.setTypeface(face);
			    mainButton.setOnClickListener(this);
			    dialog.show();
			    
	    	break;
		}
		return super.onKeyDown(keyCode, event);
	}

	/* (non-Javadoc)
	 * @see es.drOsu.game.GameNew#resume()
	 */
	@Override
	public void resume() {
		// TODO Auto-generated method stub
		super.resume();
		Log.d(TAG,"resume firsttime: "+firsttime);
		if(firsttime==false){
			Music.resume(mContex);
			startUpdateTimer();
		}
		if(paused){
			halt();
			try {
				finalize();
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}
	
	
//tratamiento de los sensores.
	/* (non-Javadoc)
 * @see android.hardware.SensorEventListener#onAccuracyChanged(android.hardware.Sensor, int)
 */
@Override
	public void onAccuracyChanged(Sensor arg0, int arg1) {
		// TODO Auto-generated method stub
		
	}

	/* (non-Javadoc)
	 * @see android.hardware.SensorEventListener#onSensorChanged(android.hardware.SensorEvent)
	 */
	@Override
	public void onSensorChanged(SensorEvent event) {
		// TODO Auto-generated method stub
		 switch(event.sensor.getType()) {
         case Sensor.TYPE_ACCELEROMETER:
                 mAccelerometerValues = event.values.clone();
                 //Log.d(TAG, "mOrientation tiene en onsensorchanged:" + mOrientationValues[0] + "-" + mOrientationValues[1]);
                 //shakebarView.invalidate();
                 if(shakebar)
                	 postInvalidate();
             break;
   	      case Sensor.TYPE_MAGNETIC_FIELD:
   	        mMagneticValues = event.values.clone();
   	        break;
		 }

   	      if (mMagneticValues != null && mAccelerometerValues != null && orientation) {
   	        float[] R = new float[16];
   	        SensorManager.getRotationMatrix(R, null, mAccelerometerValues, mMagneticValues);
   	        float[] orientation = new float[3];
   	        SensorManager.getOrientation(R, orientation);
   	        //Log.d(TAG, "grados: "+Math.toDegrees(orientation[0]));
   	        mOrientationValues[0]=(float) Math.toDegrees(orientation[0]);
   	        if(mOrientationValues[0]<0){
   	        	mOrientationValues[0]+=360;
   	        }
   	        postInvalidate();
   	      }
	}

	/* (non-Javadoc)
	 * @see android.view.View.OnClickListener#onClick(android.view.View)
	 */
	@Override
	public void onClick(View v) {
		Bundle newBundle =  new Bundle();
		 switch (v.getId()){
			 case(R.id.Button_Menu_Pause_Retry):
				 Intent intentNewGame = new Intent(mContex,GameNewActivity.class);
			 	 
			 	 newBundle.putString(Constants.keyPath, musicPath);
			 	 newBundle.putString(Constants.keyUser, user);
			 	 newBundle.putInt(Constants.keyGameMode, gameMode);
			 	 newBundle.putInt(Constants.keyGameDifficulty, gameDifficulty);
			 	 paused=true;
				 resume();
				 intentNewGame.putExtras(newBundle);
				 
				 mContex.startActivity(intentNewGame);
				 break;
			 case(R.id.Button_Menu_Pause_Choose):
				 Intent intentGame = new Intent(mContex,Game.class);
		 	 	 newBundle.putString(Constants.keyUser, user);
		 	 	 newBundle.putInt(Constants.keyGameMode, gameMode);
		 	 	 newBundle.putInt(Constants.keyGameDifficulty, gameDifficulty);
		 	 	 paused=true;
		 	 	 resume();
		 	 	 intentGame.putExtras(newBundle);
		 	 	 
		 	 	//((GameNewView)((GameNewActivity)this.getParent()).getView()).freeMemory();
			 	 mContex.startActivity(intentGame);
				 break;
			 case (R.id.Button_Menu_Pause_Main):
				dialog.dismiss();
				Intent intentMain = new Intent(mContex, DrosuMain.class);
				paused=true;
				resume();
				mContex.startActivity(intentMain);
				break;
			default:
				freeMemory();
				break;
		 }
	}
	
}